﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Xml.Serialization;
using ElectronicCommerce.Framework.ServiceModel.WCF.BindingMessage;

namespace ElectronicCommerce.Framework.ServiceModel.WCF.TransferElement
{
    public class NetMsmqBindingHandler : IGetBindingByConfig
    {
        #region IGetBindingByConfig Members

        public System.ServiceModel.Channels.Binding GetBindingMsgByConfig(string configStr)
        {
            if (string.IsNullOrEmpty(configStr))
                return new NetMsmqBinding();
            else
            {
                XmlSerializer serial = new XmlSerializer(typeof(NetMsmqBindingMsg));
                NetMsmqBindingMsg bindingMsg = (NetMsmqBindingMsg)serial.Deserialize(new StringReader(configStr));

                return GetBindingFromMsg(bindingMsg);
            }
        }

        #endregion

        private NetMsmqBinding GetBindingFromMsg(NetMsmqBindingMsg bindingMsg)
        {
            NetMsmqBinding binding = new NetMsmqBinding();
            if (bindingMsg.closeTimeout != null)
            {
                binding.CloseTimeout = TimeSpan.Parse(bindingMsg.closeTimeout);
            }
            if (bindingMsg.customDeadLetterQueue != null)
            {
                binding.CustomDeadLetterQueue = new Uri(bindingMsg.customDeadLetterQueue);
            }
            binding.DeadLetterQueue = (DeadLetterQueue)bindingMsg.deadLetterQueue;
            binding.Durable = bindingMsg.durable;
            binding.ExactlyOnce = bindingMsg.exactlyOnce;
            binding.MaxBufferPoolSize = bindingMsg.maxBufferPoolSize;
            binding.MaxReceivedMessageSize = bindingMsg.maxReceivedMessageSize;
            binding.MaxRetryCycles = bindingMsg.maxRetryCycles;
            if (bindingMsg.name != null)
            {
                binding.Name = bindingMsg.name;
            }
            if (bindingMsg.openTimeout != null)
            {
                binding.OpenTimeout = TimeSpan.Parse(bindingMsg.openTimeout);
            }
            binding.QueueTransferProtocol = (QueueTransferProtocol)bindingMsg.queueTransferProtocol;
            if (bindingMsg.readerQuotas != null)
            {
                binding.ReaderQuotas.MaxArrayLength = bindingMsg.readerQuotas.maxArrayLength;
                binding.ReaderQuotas.MaxBytesPerRead = bindingMsg.readerQuotas.maxBytesPerRead;
                binding.ReaderQuotas.MaxDepth = bindingMsg.readerQuotas.maxDepth;
                binding.ReaderQuotas.MaxNameTableCharCount = bindingMsg.readerQuotas.maxNameTableCharCount;
                binding.ReaderQuotas.MaxStringContentLength = bindingMsg.readerQuotas.maxStringContentLength;
            }
            binding.ReceiveErrorHandling = (ReceiveErrorHandling)bindingMsg.receiveErrorHandling;
            binding.ReceiveRetryCount = bindingMsg.receiveRetryCount;
            if (bindingMsg.receiveTimeout != null)
            {
                binding.ReceiveTimeout = TimeSpan.Parse(bindingMsg.receiveTimeout);
            }
            if (bindingMsg.retryCycleDelay != null)
            {
                binding.RetryCycleDelay = TimeSpan.Parse(bindingMsg.retryCycleDelay);
            }
            if (bindingMsg.sendTimeout != null)
            {
                binding.SendTimeout = TimeSpan.Parse(bindingMsg.sendTimeout);
            }
            if (bindingMsg.timeToLive != null)
            {
                binding.TimeToLive = TimeSpan.Parse(bindingMsg.timeToLive);
            }
            binding.UseActiveDirectory = bindingMsg.useActiveDirectory;
            binding.UseMsmqTracing = bindingMsg.useMsmqTracing;
            binding.UseSourceJournal = bindingMsg.useSourceJournal;

            TranNetMsmqSecurity(bindingMsg, binding);

            return binding;
        }

        private void TranNetMsmqSecurity(NetMsmqBindingMsg bindingMsg, NetMsmqBinding binding)
        {
            switch (bindingMsg.security.mode)
            {
                case NetMsmqBindingMsgSecurityMode.None:
                    binding.Security.Mode = NetMsmqSecurityMode.None;
                    break;
                case NetMsmqBindingMsgSecurityMode.Message:
                    binding.Security.Mode = NetMsmqSecurityMode.Message;
                    binding.Security.Message.AlgorithmSuite = (System.ServiceModel.Security.SecurityAlgorithmSuite)Convert.ChangeType(bindingMsg.security.message.algorithmSuite, typeof(System.ServiceModel.Security.SecurityAlgorithmSuite));// bindingMsg.Security.Message.AlgorithmSuite;
                    binding.Security.Message.ClientCredentialType = (MessageCredentialType)bindingMsg.security.message.clientCredentialType;
                    break;
                case NetMsmqBindingMsgSecurityMode.Transport:
                    binding.Security.Mode = NetMsmqSecurityMode.Transport;
                    binding.Security.Transport.MsmqAuthenticationMode = (MsmqAuthenticationMode)bindingMsg.security.transport.msmqAuthenticationMode;
                    binding.Security.Transport.MsmqEncryptionAlgorithm = (MsmqEncryptionAlgorithm)bindingMsg.security.transport.msmqEncryptionAlgorithm;
                    binding.Security.Transport.MsmqProtectionLevel = (System.Net.Security.ProtectionLevel)bindingMsg.security.transport.msmqProtectionLevel;
                    binding.Security.Transport.MsmqSecureHashAlgorithm = (MsmqSecureHashAlgorithm)bindingMsg.security.transport.msmqSecureHashAlgorithm;
                    break;
                case NetMsmqBindingMsgSecurityMode.Both:
                    binding.Security.Mode = NetMsmqSecurityMode.Both;
                    binding.Security.Message.AlgorithmSuite = (System.ServiceModel.Security.SecurityAlgorithmSuite)Convert.ChangeType(bindingMsg.security.message.algorithmSuite, typeof(System.ServiceModel.Security.SecurityAlgorithmSuite));// bindingMsg.Security.Message.AlgorithmSuite;
                    binding.Security.Message.ClientCredentialType = (MessageCredentialType)bindingMsg.security.message.clientCredentialType;
                    binding.Security.Transport.MsmqAuthenticationMode = (MsmqAuthenticationMode)bindingMsg.security.transport.msmqAuthenticationMode;
                    binding.Security.Transport.MsmqEncryptionAlgorithm = (MsmqEncryptionAlgorithm)bindingMsg.security.transport.msmqEncryptionAlgorithm;
                    binding.Security.Transport.MsmqProtectionLevel = (System.Net.Security.ProtectionLevel)bindingMsg.security.transport.msmqProtectionLevel;
                    binding.Security.Transport.MsmqSecureHashAlgorithm = (MsmqSecureHashAlgorithm)bindingMsg.security.transport.msmqSecureHashAlgorithm;
                    break;
                default:
                    binding.Security.Mode = NetMsmqSecurityMode.None;
                    break;
            }
        }



        #region IGetBindingByConfig Members


        public string GetAddress(string templateAddress)
        {
            return String.Format("net.msmq://{0}", templateAddress);
        }
        #endregion
    }
}
